In this assignment, you will perform fundamental analysis for the Toronto dwellings market to allow potential real estate investors to choose rental investment properties.
# imports
import panel as pn
pn.extension('plotly')
import plotly.express as px
import pandas as pd
import hvplot.pandas
import matplotlib.pyplot as plt
import os
from pathlib import Path
from dotenv import load_dotenv
import random
# Read the Mapbox API key
load_dotenv()
map_box_api = os.getenv("MAPBOX_API_KEY")
# Set the Mapbox API
px.set_mapbox_access_token(map_box_api)
# Read the census data into a Pandas DataFrame
file_path = Path("Data/toronto_neighbourhoods_census_data.csv")
to_data = pd.read_csv(file_path, index_col="year")
to_data.head()
| neighbourhood | single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | average_house_value | shelter_costs_owned | shelter_costs_rented | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | ||||||||||||
| 2001 | Agincourt North | 3715 | 1480 | 0 | 1055 | 1295 | 195 | 185 | 5 | 200388 | 810 | 870 |
| 2001 | Agincourt South-Malvern West | 3250 | 1835 | 0 | 545 | 455 | 105 | 425 | 0 | 203047 | 806 | 892 |
| 2001 | Alderwood | 3175 | 315 | 0 | 470 | 50 | 185 | 370 | 0 | 259998 | 817 | 924 |
| 2001 | Annex | 1060 | 6090 | 5 | 1980 | 605 | 275 | 3710 | 165 | 453850 | 1027 | 1378 |
| 2001 | Banbury-Don Mills | 3615 | 4465 | 0 | 240 | 380 | 15 | 1360 | 0 | 371864 | 1007 | 1163 |
In this section, you will calculate the number of dwelling types per year. Visualize the results using bar charts and the Pandas plot function.
Hint: Use the Pandas groupby function.
Optional challenge: Plot each bar chart in a different color.
# Calculate the sum number of dwelling types units per year (hint: use groupby)
#We will also drop the columns which are not the dwelling types
dwellings_per_year = to_data.groupby("year").sum().drop(columns=["average_house_value", "shelter_costs_owned", "shelter_costs_rented" ])
dwellings_per_year
| single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | |
|---|---|---|---|---|---|---|---|---|
| year | ||||||||
| 2001 | 300930 | 355015 | 75 | 90995 | 52355 | 23785 | 116900 | 3040 |
| 2006 | 266860 | 379400 | 165 | 69430 | 54690 | 44095 | 162850 | 1335 |
| 2011 | 274940 | 429220 | 100 | 72480 | 60355 | 44750 | 163895 | 2165 |
| 2016 | 269680 | 493270 | 95 | 71200 | 61565 | 48585 | 165575 | 2845 |
# Save the dataframe as a csv file
dwellings_per_year.to_csv("Data/dwelling_types_per_year.csv")
# Helper create_bar_chart function
def create_bar_chart(data, title, xlabel, ylabel, color):
"""
Create a barplot based in the data argument.
Input:
data = DataFrame to use for plotting the data
title = Chart Title
xlabel = Label for X Axis
ylabel = Label for Y Axis
color = Colour of the bar chart
"""
data.plot(kind="bar", xlabel=xlabel, ylabel=ylabel, color=color, title=title)
#We want to show the plot after plotting it, if we dont do this, it will overwrite the previously plotted bar chart.
plt.show()
# Create a bar chart per year to show the number of dwelling types
colors = ["red", "pink", "blue", "yellow"]
#We will use a for loop to do charts for each year rather than repeating the code and we will use a random color from the colors list.
for index in dwellings_per_year.index:
title = "Dwelling Types in Toranto in " + str(index)
ylabel = "Dwelling Type Units"
create_bar_chart(dwellings_per_year.loc[index], title=title, xlabel=index, ylabel=ylabel, color=random.choice(colors))
In this section, you will calculate the average monthly shelter costs for owned and rented dwellings and the average house value for each year. Plot the results as a line chart.
Optional challenge: Plot each line chart in a different color.
# Calculate the average monthly shelter costs for owned and rented dwellings
#We will also drop the columns which are not the dwelling types
#dwellings_per_year = to_data[[]].groupby("year").mean().drop(columns=["average_house_value", "shelter_costs_owned", "shelter_costs_rented" ])
monthly_shelter_cost_per_year = to_data[["shelter_costs_owned","shelter_costs_rented"]].groupby("year").mean()
monthly_shelter_cost_per_year
| shelter_costs_owned | shelter_costs_rented | |
|---|---|---|
| year | ||
| 2001 | 846.878571 | 1085.935714 |
| 2006 | 1316.800000 | 925.414286 |
| 2011 | 1448.214286 | 1019.792857 |
| 2016 | 1761.314286 | 1256.321429 |
# Helper create_line_chart function
def create_line_chart(data, title, xlabel, ylabel, color):
"""
Create a line chart based in the data argument.
Input:
data = DataFrame to use for plotting the data
title = Chart Title
xlabel = Label for X Axis
ylabel = Label for Y Axis
color = Colour of the bar chart
"""
data.plot(kind="line", xlabel=xlabel, ylabel=ylabel, color=color, title=title)
#We want to show the plot after plotting it, if we dont do this, it will overwrite the previously plotted bar chart.
plt.show()
# Create two line charts, one to plot the monthly shelter costs for owned dwelleing and other for rented dwellings per year
# Line chart for owned dwellings
create_line_chart(data=monthly_shelter_cost_per_year["shelter_costs_owned"], title="Average Monthly Shelter Cost for Owned Dwellings in Toronto ",
xlabel="Year", ylabel="Average Monthly Shelter Costs", color="red")
# Line chart for rented dwellings
create_line_chart(data=monthly_shelter_cost_per_year["shelter_costs_rented"], title="Average Monthly Shelter Cost for Rented Dwellings in Toronto ",
xlabel="Year", ylabel="Average Monthly Shelter Costs", color="yellow")
In this section, you want to determine the average house value per year. An investor may want to understand better the sales price of the rental property over time. For example, a customer will want to know if they should expect an increase or decrease in the property value over time so they can determine how long to hold the rental property. You will visualize the average_house_value per year as a bar chart.
# Calculate the average house value per year
average_house_value = to_data["average_house_value"].groupby("year").mean()
average_house_value
year 2001 289882.885714 2006 424059.664286 2011 530424.721429 2016 664068.328571 Name: average_house_value, dtype: float64
# Plot the average house value per year as a line chart
create_line_chart(data=average_house_value, title="Average House Value in Toronto ",
xlabel="Year", ylabel="Average House Value", color="blue")
In this section, you will use hvplot to create an interactive visualization of the average house value with a dropdown selector for the neighbourhood.
Hint: It will be easier to create a new DataFrame from grouping the data and calculating the mean house values for each year and neighbourhood.
# Create a new DataFrame with the mean house values by neighbourhood per year
avg_house_value_by_neighbourhood = to_data[["neighbourhood","average_house_value"]].reset_index()
avg_house_value_by_neighbourhood.head(10)
| year | neighbourhood | average_house_value | |
|---|---|---|---|
| 0 | 2001 | Agincourt North | 200388 |
| 1 | 2001 | Agincourt South-Malvern West | 203047 |
| 2 | 2001 | Alderwood | 259998 |
| 3 | 2001 | Annex | 453850 |
| 4 | 2001 | Banbury-Don Mills | 371864 |
| 5 | 2001 | Bathurst Manor | 304749 |
| 6 | 2001 | Bay Street Corridor | 257404 |
| 7 | 2001 | Bayview Village | 327644 |
| 8 | 2001 | Bayview Woods-Steeles | 343535 |
| 9 | 2001 | Bedford Park-Nortown | 565304 |
# Use hvplot to create an interactive line chart of the average house value per neighbourhood
# The plot should have a dropdown selector for the neighbourhood
avg_house_value_by_neighbourhood.hvplot.line(x="year", y="average_house_value", xlabel="Year", ylabel="Average House Value", groupby="neighbourhood")
In this section, you will use hvplot to create an interactive visualization of the average number of dwelling types per year with a dropdown selector for the neighbourhood.
# Fetch the data of all dwelling types per year
dwelling_types_per_year = to_data.drop(columns=["average_house_value", "shelter_costs_owned", "shelter_costs_rented" ])
dwelling_types_per_year.head(10)
| neighbourhood | single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | |
|---|---|---|---|---|---|---|---|---|---|
| year | |||||||||
| 2001 | Agincourt North | 3715 | 1480 | 0 | 1055 | 1295 | 195 | 185 | 5 |
| 2001 | Agincourt South-Malvern West | 3250 | 1835 | 0 | 545 | 455 | 105 | 425 | 0 |
| 2001 | Alderwood | 3175 | 315 | 0 | 470 | 50 | 185 | 370 | 0 |
| 2001 | Annex | 1060 | 6090 | 5 | 1980 | 605 | 275 | 3710 | 165 |
| 2001 | Banbury-Don Mills | 3615 | 4465 | 0 | 240 | 380 | 15 | 1360 | 0 |
| 2001 | Bathurst Manor | 2405 | 1550 | 0 | 130 | 130 | 375 | 745 | 0 |
| 2001 | Bay Street Corridor | 10 | 7575 | 0 | 0 | 15 | 0 | 240 | 0 |
| 2001 | Bayview Village | 2170 | 630 | 0 | 170 | 765 | 15 | 640 | 0 |
| 2001 | Bayview Woods-Steeles | 1650 | 1715 | 0 | 925 | 105 | 10 | 170 | 5 |
| 2001 | Bedford Park-Nortown | 4985 | 2080 | 0 | 45 | 40 | 210 | 1235 | 15 |
# Use hvplot to create an interactive bar chart of the number of dwelling types per neighbourhood
# The plot should have a dropdown selector for the neighbourhood
dwelling_types_per_year.hvplot.bar(groupby="neighbourhood",rot=90, ylabel="Dwelling Type Units", xlabel="Year", height=500)
In this section, you will need to calculate the house value for each neighbourhood and then sort the values to obtain the top 10 most expensive neighbourhoods on average. Plot the results as a bar chart.
# Getting the data from the top 10 expensive neighbourhoods
ten_expensive_neighbourhoods = to_data.groupby("neighbourhood").mean().sort_values(by="average_house_value", ascending=False).reset_index()
ten_expensive_neighbourhoods.head(10)
| neighbourhood | single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | average_house_value | shelter_costs_owned | shelter_costs_rented | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Bridle Path-Sunnybrook-York Mills | 2260.00 | 331.25 | 0.00 | 36.25 | 90.00 | 25.0 | 40.00 | 0.00 | 1526485.75 | 2360.75 | 2321.75 |
| 1 | Forest Hill South | 1742.50 | 2031.25 | 1.25 | 61.25 | 45.00 | 75.0 | 1027.50 | 3.75 | 1195992.50 | 1781.00 | 1313.75 |
| 2 | Lawrence Park South | 3472.50 | 773.75 | 0.00 | 126.25 | 38.75 | 225.0 | 966.25 | 16.25 | 1094027.75 | 1954.00 | 1372.75 |
| 3 | Rosedale-Moore Park | 2498.75 | 4641.25 | 0.00 | 486.25 | 245.00 | 327.5 | 1618.75 | 2.50 | 1093640.00 | 1909.75 | 1537.25 |
| 4 | St.Andrew-Windfields | 3225.00 | 1670.00 | 0.00 | 185.00 | 552.50 | 97.5 | 586.25 | 5.00 | 999107.00 | 1880.25 | 1384.50 |
| 5 | Casa Loma | 916.25 | 2310.00 | 0.00 | 288.75 | 201.25 | 162.5 | 1192.50 | 2.50 | 981064.25 | 1873.75 | 1547.75 |
| 6 | Bedford Park-Nortown | 4865.00 | 1981.25 | 0.00 | 43.75 | 57.50 | 287.5 | 1275.00 | 88.75 | 930415.25 | 1786.75 | 1255.00 |
| 7 | Forest Hill North | 1488.75 | 3392.50 | 0.00 | 12.50 | 16.25 | 82.5 | 402.50 | 1.25 | 851680.50 | 1722.75 | 1245.50 |
| 8 | Kingsway South | 2326.25 | 576.25 | 0.00 | 66.25 | 48.75 | 20.0 | 336.25 | 2.50 | 843234.25 | 1736.75 | 1622.00 |
| 9 | Yonge-St.Clair | 565.00 | 3948.75 | 0.00 | 425.00 | 212.50 | 172.5 | 1308.75 | 6.25 | 813220.25 | 1680.75 | 1369.00 |
# Plotting the data from the top 10 expensive neighbourhoods
ten_expensive_neighbourhoods.head(10).hvplot.bar(rot=90, ylabel="Average House Value", xlabel="Neighbourhood", y="average_house_value", x="neighbourhood",height=500)
#ten_expensive_neighbourhoods[["average_house_value","shelter_costs_rented"]]
In this section, you will read in neighbourhoods location data and build an interactive map with the average house value per neighbourhood. Use a scatter_mapbox from Plotly express to create the visualization. Remember, you will need your Mapbox API key for this.
# Load neighbourhoods coordinates data
file_path = Path("Data/toronto_neighbourhoods_coordinates.csv")
df_neighbourhood_locations = pd.read_csv(file_path)
df_neighbourhood_locations
| neighbourhood | lat | lon | |
|---|---|---|---|
| 0 | Agincourt North | 43.805441 | -79.266712 |
| 1 | Agincourt South-Malvern West | 43.788658 | -79.265612 |
| 2 | Alderwood | 43.604937 | -79.541611 |
| 3 | Annex | 43.671585 | -79.404001 |
| 4 | Banbury-Don Mills | 43.737657 | -79.349718 |
| ... | ... | ... | ... |
| 135 | Wychwood | 43.676919 | -79.425515 |
| 136 | Yonge-Eglinton | 43.704689 | -79.403590 |
| 137 | Yonge-St.Clair | 43.687859 | -79.397871 |
| 138 | York University Heights | 43.765736 | -79.488883 |
| 139 | Yorkdale-Glen Park | 43.714672 | -79.457108 |
140 rows × 3 columns
You will need to join the location data with the mean values per neighbourhood.
Calculate the mean values for each neighbourhood.
Join the average values with the neighbourhood locations.
# Calculate the mean values for each neighborhood
mean_data_neighbourhoods = to_data.groupby("neighbourhood").mean().reset_index()
mean_data_neighbourhoods.head()
| neighbourhood | single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | average_house_value | shelter_costs_owned | shelter_costs_rented | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Agincourt North | 3435.00 | 1947.50 | 2.50 | 863.75 | 1406.25 | 512.50 | 547.50 | 10.00 | 329811.5 | 1109.00 | 983.50 |
| 1 | Agincourt South-Malvern West | 2897.50 | 2180.00 | 1.25 | 375.00 | 456.25 | 523.75 | 628.75 | 32.50 | 334189.0 | 1131.25 | 985.00 |
| 2 | Alderwood | 2903.75 | 302.50 | 1.25 | 503.75 | 76.25 | 302.50 | 502.50 | 1.25 | 427922.5 | 1166.75 | 1003.25 |
| 3 | Annex | 751.25 | 7235.00 | 1.25 | 1375.00 | 613.75 | 355.00 | 4605.00 | 83.75 | 746977.0 | 1692.75 | 1315.25 |
| 4 | Banbury-Don Mills | 3572.50 | 5388.75 | 1.25 | 273.75 | 626.25 | 32.50 | 1340.00 | 0.00 | 612039.0 | 1463.50 | 1242.75 |
#Set the index to neighbourhood so we join without any errors or inaccuracies
mean_data_neighbourhoods.set_index(keys="neighbourhood",inplace=True)
df_neighbourhood_locations.set_index(keys="neighbourhood",inplace=True)
# Join the average values with the neighbourhood locations
neighbourhood_with_location = pd.concat([mean_data_neighbourhoods, df_neighbourhood_locations ], join="inner", axis="columns")
neighbourhood_with_location
| single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | average_house_value | shelter_costs_owned | shelter_costs_rented | lat | lon | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| neighbourhood | |||||||||||||
| Agincourt North | 3435.00 | 1947.50 | 2.50 | 863.75 | 1406.25 | 512.50 | 547.50 | 10.00 | 329811.50 | 1109.00 | 983.50 | 43.805441 | -79.266712 |
| Agincourt South-Malvern West | 2897.50 | 2180.00 | 1.25 | 375.00 | 456.25 | 523.75 | 628.75 | 32.50 | 334189.00 | 1131.25 | 985.00 | 43.788658 | -79.265612 |
| Alderwood | 2903.75 | 302.50 | 1.25 | 503.75 | 76.25 | 302.50 | 502.50 | 1.25 | 427922.50 | 1166.75 | 1003.25 | 43.604937 | -79.541611 |
| Annex | 751.25 | 7235.00 | 1.25 | 1375.00 | 613.75 | 355.00 | 4605.00 | 83.75 | 746977.00 | 1692.75 | 1315.25 | 43.671585 | -79.404001 |
| Banbury-Don Mills | 3572.50 | 5388.75 | 1.25 | 273.75 | 626.25 | 32.50 | 1340.00 | 0.00 | 612039.00 | 1463.50 | 1242.75 | 43.737657 | -79.349718 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| Wychwood | 1056.25 | 1236.25 | 0.00 | 992.50 | 298.75 | 325.00 | 1878.75 | 17.50 | 565976.50 | 1390.75 | 1017.25 | 43.676919 | -79.425515 |
| Yonge-Eglinton | 1468.75 | 1638.75 | 0.00 | 470.00 | 33.75 | 328.75 | 1385.00 | 6.25 | 809745.75 | 1799.50 | 1347.75 | 43.704689 | -79.403590 |
| Yonge-St.Clair | 565.00 | 3948.75 | 0.00 | 425.00 | 212.50 | 172.50 | 1308.75 | 6.25 | 813220.25 | 1680.75 | 1369.00 | 43.687859 | -79.397871 |
| York University Heights | 1355.00 | 5165.00 | 1.25 | 1316.25 | 662.50 | 188.75 | 1085.00 | 33.75 | 305899.50 | 1116.75 | 937.50 | 43.765736 | -79.488883 |
| Yorkdale-Glen Park | 2286.25 | 1347.50 | 0.00 | 73.75 | 450.00 | 377.50 | 722.50 | 7.50 | 430861.25 | 1122.50 | 942.50 | 43.714672 | -79.457108 |
140 rows × 13 columns
Plot the average values per neighbourhood using a Plotly express scatter_mapbox visualization.
# Create a scatter mapbox to analyze neighbourhood info
avg_house_value_map= px.scatter_mapbox(
neighbourhood_with_location,
lat="lat",
lon="lon",
color="average_house_value", title="Average House Value in Toronto"
)
avg_house_value_map.show()
In this section, you will use Plotly express to a couple of plots that investors can interactively filter and explore various factors related to the house value of the Toronto's neighbourhoods.
mean_data_neighbourhoods.reset_index(inplace=True)
to_data
| neighbourhood | single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | average_house_value | shelter_costs_owned | shelter_costs_rented | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | ||||||||||||
| 2001 | Agincourt North | 3715 | 1480 | 0 | 1055 | 1295 | 195 | 185 | 5 | 200388 | 810 | 870 |
| 2001 | Agincourt South-Malvern West | 3250 | 1835 | 0 | 545 | 455 | 105 | 425 | 0 | 203047 | 806 | 892 |
| 2001 | Alderwood | 3175 | 315 | 0 | 470 | 50 | 185 | 370 | 0 | 259998 | 817 | 924 |
| 2001 | Annex | 1060 | 6090 | 5 | 1980 | 605 | 275 | 3710 | 165 | 453850 | 1027 | 1378 |
| 2001 | Banbury-Don Mills | 3615 | 4465 | 0 | 240 | 380 | 15 | 1360 | 0 | 371864 | 1007 | 1163 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2016 | Wychwood | 920 | 1295 | 0 | 880 | 290 | 395 | 2080 | 35 | 787760 | 1864 | 1146 |
| 2016 | Yonge-Eglinton | 1400 | 1995 | 0 | 465 | 60 | 310 | 1445 | 0 | 1127052 | 2398 | 1535 |
| 2016 | Yonge-St.Clair | 520 | 4315 | 0 | 450 | 220 | 130 | 1370 | 0 | 1131888 | 2192 | 1619 |
| 2016 | York University Heights | 1235 | 5505 | 0 | 1360 | 775 | 280 | 995 | 0 | 425769 | 1444 | 1122 |
| 2016 | Yorkdale-Glen Park | 2165 | 1185 | 0 | 80 | 600 | 465 | 830 | 5 | 599698 | 1451 | 1128 |
560 rows × 12 columns
px.bar(to_data, x="neighbourhood", y="average_house_value",color="average_house_value", facet_row=to_data.index,height=1000, title="Average House Values in Toronto Per Neighbourhood" )
# Fetch the data from all expensive neighbourhoods per year.
ten_most_expensive_neighbourhoods_per_year = to_data.sort_values(by="average_house_value", ascending=False).groupby('year').head(10)
ten_most_expensive_neighbourhoods_per_year
| neighbourhood | single_detached_house | apartment_five_storeys_plus | movable_dwelling | semi_detached_house | row_house | duplex | apartment_five_storeys_less | other_house | average_house_value | shelter_costs_owned | shelter_costs_rented | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | ||||||||||||
| 2016 | Bridle Path-Sunnybrook-York Mills | 2275 | 590 | 0 | 40 | 230 | 30 | 80 | 0 | 2124653 | 2903 | 2942 |
| 2011 | Bridle Path-Sunnybrook-York Mills | 2285 | 480 | 0 | 45 | 100 | 30 | 50 | 0 | 1697067 | 2387 | 2388 |
| 2016 | Forest Hill South | 1685 | 2025 | 0 | 65 | 40 | 70 | 1050 | 0 | 1664653 | 2383 | 1486 |
| 2016 | Lawrence Park South | 3420 | 925 | 0 | 110 | 35 | 230 | 1015 | 5 | 1522732 | 2644 | 1515 |
| 2016 | Rosedale-Moore Park | 2450 | 4990 | 0 | 485 | 260 | 345 | 1505 | 5 | 1522193 | 2498 | 1809 |
| 2016 | St.Andrew-Windfields | 3245 | 1745 | 0 | 175 | 540 | 120 | 595 | 5 | 1390616 | 2516 | 1565 |
| 2016 | Casa Loma | 875 | 2680 | 0 | 265 | 200 | 155 | 1225 | 0 | 1365503 | 2434 | 1841 |
| 2006 | Bridle Path-Sunnybrook-York Mills | 2205 | 145 | 0 | 35 | 15 | 30 | 10 | 0 | 1356757 | 2170 | 2167 |
| 2011 | Forest Hill South | 1730 | 1825 | 0 | 65 | 45 | 75 | 1035 | 0 | 1329642 | 1959 | 1206 |
| 2016 | Bedford Park-Nortown | 4820 | 1995 | 0 | 45 | 65 | 315 | 1260 | 115 | 1295007 | 2418 | 1385 |
| 2011 | Lawrence Park South | 3465 | 855 | 0 | 115 | 25 | 230 | 980 | 10 | 1216283 | 2174 | 1230 |
| 2011 | Rosedale-Moore Park | 2485 | 4905 | 0 | 495 | 250 | 345 | 1550 | 0 | 1215852 | 2054 | 1468 |
| 2016 | Forest Hill North | 1470 | 3430 | 0 | 15 | 30 | 110 | 385 | 0 | 1185419 | 2316 | 1395 |
| 2016 | Kingsway South | 2310 | 790 | 0 | 70 | 50 | 30 | 335 | 0 | 1173663 | 2173 | 2020 |
| 2016 | Yonge-St.Clair | 520 | 4315 | 0 | 450 | 220 | 130 | 1370 | 0 | 1131888 | 2192 | 1619 |
| 2011 | St.Andrew-Windfields | 3285 | 1740 | 0 | 180 | 555 | 120 | 580 | 10 | 1110755 | 2069 | 1270 |
| 2011 | Casa Loma | 880 | 2630 | 0 | 245 | 220 | 140 | 1215 | 0 | 1090696 | 2001 | 1494 |
| 2006 | Forest Hill South | 1740 | 1835 | 0 | 50 | 50 | 70 | 1015 | 0 | 1063011 | 1781 | 1094 |
| 2011 | Bedford Park-Nortown | 4870 | 1960 | 0 | 40 | 65 | 335 | 1320 | 115 | 1034387 | 1988 | 1124 |
| 2006 | Lawrence Park South | 3415 | 745 | 0 | 110 | 25 | 250 | 1025 | 10 | 972384 | 1977 | 1116 |
| 2006 | Rosedale-Moore Park | 2450 | 4790 | 0 | 445 | 245 | 330 | 1685 | 5 | 972039 | 1868 | 1332 |
| 2011 | Forest Hill North | 1470 | 3350 | 0 | 15 | 25 | 105 | 365 | 0 | 946854 | 1904 | 1132 |
| 2011 | Kingsway South | 2350 | 695 | 0 | 70 | 50 | 25 | 335 | 0 | 937464 | 1787 | 1640 |
| 2001 | Bridle Path-Sunnybrook-York Mills | 2275 | 110 | 0 | 25 | 15 | 10 | 20 | 0 | 927466 | 1983 | 1790 |
| 2011 | Yonge-St.Clair | 530 | 4070 | 0 | 450 | 220 | 135 | 1380 | 0 | 904096 | 1802 | 1314 |
| 2006 | St.Andrew-Windfields | 3095 | 1740 | 0 | 165 | 560 | 105 | 645 | 0 | 888017 | 1881 | 1152 |
| 2006 | Casa Loma | 875 | 2230 | 0 | 230 | 195 | 170 | 1240 | 5 | 871981 | 1819 | 1356 |
| 2006 | Bedford Park-Nortown | 4785 | 1890 | 0 | 45 | 60 | 290 | 1285 | 110 | 826963 | 1808 | 1020 |
| 2006 | Forest Hill North | 1450 | 3410 | 0 | 10 | 10 | 115 | 375 | 0 | 756983 | 1731 | 1027 |
| 2006 | Kingsway South | 2275 | 560 | 0 | 60 | 50 | 25 | 335 | 0 | 749476 | 1625 | 1488 |
| 2001 | Forest Hill South | 1815 | 2440 | 5 | 65 | 45 | 85 | 1010 | 15 | 726664 | 1001 | 1469 |
| 2006 | Yonge-St.Clair | 540 | 3785 | 0 | 390 | 210 | 145 | 1465 | 0 | 722799 | 1638 | 1192 |
| 2001 | Lawrence Park South | 3590 | 570 | 0 | 170 | 70 | 190 | 845 | 40 | 664712 | 1021 | 1630 |
| 2001 | Rosedale-Moore Park | 2610 | 3880 | 0 | 520 | 225 | 290 | 1735 | 0 | 664476 | 1219 | 1540 |
| 2001 | St.Andrew-Windfields | 3275 | 1455 | 0 | 220 | 555 | 45 | 525 | 5 | 607040 | 1055 | 1551 |
| 2001 | Casa Loma | 1035 | 1700 | 0 | 415 | 190 | 185 | 1090 | 5 | 596077 | 1241 | 1500 |
| 2001 | Bedford Park-Nortown | 4985 | 2080 | 0 | 45 | 40 | 210 | 1235 | 15 | 565304 | 933 | 1491 |
| 2001 | Forest Hill North | 1565 | 3380 | 0 | 10 | 0 | 0 | 485 | 5 | 517466 | 940 | 1428 |
| 2001 | Kingsway South | 2370 | 260 | 0 | 65 | 45 | 0 | 340 | 10 | 512334 | 1362 | 1340 |
| 2001 | Yonge-St.Clair | 670 | 3625 | 0 | 410 | 200 | 280 | 1020 | 25 | 494098 | 1091 | 1351 |
# Create the sunburst chart
px.sunburst(
ten_most_expensive_neighbourhoods_per_year,
path=[ten_most_expensive_neighbourhoods_per_year.index, 'neighbourhood'], values='average_house_value', color='average_house_value', color_continuous_scale='blues',
height=500
)